package com.itbaizhan.cxpt.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.itbaizhan.cxpt.config.RetryConfig;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class MoonshotService {

    @Value("${moonshot.api.base-url}")
    private String baseUrl;

    @Value("${moonshot.api.key}")
    private String apiKey;

    @Value("${moonshot.api.endpoints.chat}")
    private String chatEndpoint;

    @Value("${moonshot.api.endpoints.files}")
    private String filesEndpoint;

    @Value("${moonshot.api.endpoints.file-content}")
    private String fileContentEndpoint;

    private final OkHttpClient client = new OkHttpClient();
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RetryConfig retryConfig;

    private <T> T executeWithRetry(RetryableOperation<T> operation) throws IOException {
        int attempts = 0;
        long interval = retryConfig.getInitialIntervalMillis();
        IOException lastException = null;

        while (attempts < retryConfig.getMaxAttempts()) {
            try {
                return operation.execute();
            } catch (IOException e) {
                lastException = e;
                if (e.getMessage().contains("429")) {
                    attempts++;
                    if (attempts < retryConfig.getMaxAttempts()) {
                        try {
                            Thread.sleep(Math.min(interval, retryConfig.getMaxIntervalMillis()));
                            interval *= retryConfig.getMultiplier();
                        } catch (InterruptedException ie) {
                            Thread.currentThread().interrupt();
                            throw e;
                        }
                    }
                } else {
                    throw e;
                }
            }
        }
        throw new IOException("达到最大重试次数，请求仍然失败: " + lastException.getMessage());
    }

    @FunctionalInterface
    private interface RetryableOperation<T> {
        T execute() throws IOException;
    }

    public String uploadFile(File file) throws IOException {
        return executeWithRetry(() -> {
            RequestBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("file", file.getName(),
                            RequestBody.create(MediaType.parse("application/octet-stream"), file))
                    .addFormDataPart("purpose", "file-extract")
                    .build();

            Request request = new Request.Builder()
                    .url(baseUrl + filesEndpoint)
                    .header("Authorization", "Bearer " + apiKey)
                    .post(requestBody)
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) throw new IOException("上传文件失败: " + response);
                JsonNode jsonNode = objectMapper.readTree(response.body().string());
                return jsonNode.get("id").asText();
            }
        });
    }

    public String getFileContent(String fileId) throws IOException {
        return executeWithRetry(() -> {
            Request request = new Request.Builder()
                    .url(baseUrl + fileContentEndpoint.replace("{fileId}", fileId))
                    .header("Authorization", "Bearer " + apiKey)
                    .get()
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) throw new IOException("获取文件内容失败: " + response);
                JsonNode jsonNode = objectMapper.readTree(response.body().string());
                return jsonNode.get("text").asText();
            }
        });
    }

    public String chatCompletion(String fileContent, String userQuestion) throws IOException {
        return executeWithRetry(() -> {
            List<ObjectNode> messages = new ArrayList<>();

            ObjectNode systemMessage1 = objectMapper.createObjectNode();
            systemMessage1.put("role", "system");
            systemMessage1.put("content", "找到pdf中国标的信息，国标号，和国标名字。 还有国标存在pdf的页面。按照json给是给我返回");

            ObjectNode systemMessage2 = objectMapper.createObjectNode();
            systemMessage2.put("role", "system");
            systemMessage2.put("content", fileContent);

            ObjectNode userMessage = objectMapper.createObjectNode();
            userMessage.put("role", "user");
            userMessage.put("content", userQuestion);

            messages.add(systemMessage1);
            messages.add(systemMessage2);
            messages.add(userMessage);

            ObjectNode requestBody = objectMapper.createObjectNode();
            requestBody.put("model", "moonshot-v1-32k");
            requestBody.put("temperature", 0.3);
            requestBody.set("messages", objectMapper.valueToTree(messages));

            Request request = new Request.Builder()
                    .url(baseUrl + chatEndpoint)
                    .header("Authorization", "Bearer " + apiKey)
                    .post(RequestBody.create(
                            MediaType.parse("application/json"),
                            objectMapper.writeValueAsString(requestBody)))
                    .build();

            try (Response response = client.newCall(request).execute()) {
                if (!response.isSuccessful()) throw new IOException("聊天请求失败: " + response);
                JsonNode jsonNode = objectMapper.readTree(response.body().string());
                return jsonNode.get("choices").get(0).get("message").get("content").asText();
            }
        });
    }
}